import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Button, message, Spin, Tree, Icon, Menu, Dropdown } from 'antd';
import AddEditModal from './components/add-edit-modal';
import { cn as nzhcn } from 'nzh';
import { getStaffList } from '@api/organization';
import { getOrganization, getAllOrganization, deleteOrganization } from '@api/organization';
import { getSystemConfig } from '@api/system';
import _ from 'lodash';
import { bindActionCreators } from 'redux';
import TreeNodeTitle from './components/tree-node-title';
import StaffList from './components/staff-list';
import AddStaffModal from './components/add-staff-modal';
import AutoSyncLdapModal from './components/auto-sync-ldap-modal';
import { connect } from 'react-redux';
import { actions as assetManageActions } from '../asset-manage/reducer';
import BatchUploadOrgModal from './components/batch-upload-org-modal';
import './index.less';

const TreeNode = Tree.TreeNode;
const prefixCls = 'p-organization';

class Organization extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      search: '',
      addEditModalMode: 'add',
      addEditModalVisible: false,
      addStaffModalVisible: false,
      autoSyncLdapVisible: false,
      currentOrg: {},
      organizationCascaderTree: [], // 用于级联筛选的树
      organizationTree: [], // 所有组织架构的树结构
      expaneds: [], //展开的路径
      levelSiteCount: {},
      staffFilter: {
        pageSize: 10,
        page: 1,
        search: '',
        orgs: [],
        role: []
      },
      staffList: [],
      staffLoading: false,
      staffCount: 0,
      AllStaffCount: 0,
      editRow: null,
      selectTreeNode: '',
      batchEditStaffIds: [],
      LdapConfig: null,
      batchOrgVisible: false
    };
  }

  componentDidMount() {
    this.loadOrganizationTree('all');
    this.loadOrganizationCascaderTree();
    this.loadStaffList();
    this.loadLdapConfig();
  }

  loadLdapConfig = () => {
    getSystemConfig({ type: 'LDAP' }).then(rs => {
      const LdapConfig = _.get(rs, 'data.data.systemConfig.LDAP', null);
      this.setState({ LdapConfig });
    });
  };

  loadStaffList = () => {
    this.setState({ staffLoading: true });
    const { staffFilter } = this.state;
    const params = { ...staffFilter };
    !params.search && delete params.search;
    getStaffList(params).then(res => {
      const staffList = _.get(res, 'data.data.list', []);
      const staffCount = _.get(res, 'data.data.count', 0);
      this.setState({ staffList, staffCount, staffLoading: false });
    });
  };

  loadOrganizationTree = loadingType => {
    return new Promise(resolve => {
      let { search, expaneds } = this.state;
      const params = {};
      if (search) {
        params.search = search.trim();
      }
      if (expaneds.length) {
        params.paths = expaneds;
      }
      this.setState({ loading: loadingType });
      return getOrganization(params)
        .then(res => {
          const tree = _.get(res, 'data.data.tree', []);
          const levelSiteCount = _.get(res, 'data.data.level_site_count', []);
          this.setState({ organizationTree: tree, organizations: [tree], levelSiteCount });
        })
        .finally(() => {
          this.setState({ loading: false });
          resolve();
        });
    });
  };

  loadOrganizationCascaderTree = () => {
    getAllOrganization().then(res => {
      let tree = _.get(res, 'data.data.tree', []);
      // 计算整体架构组织共计多少人
      const AllStaffCount = tree.reduce((prev, cur) => prev + cur.staffCount, 0);
      this.setState({ organizationCascaderTree: tree, AllStaffCount });
    });
  };

  expanNextLevel = (org = {}) => {
    let { _id, level = 1 } = org;
    let { expaneds } = this.state;
    let newExpaneds = expaneds.slice(0, level - 1);
    newExpaneds.push(_id);
    this.setState({ expaneds: newExpaneds }, () => {
      this.loadOrganizationTree('next');
      setTimeout(this.scrollCurrentLaneIntoView, 100);
    });
  };

  scrollCurrentLaneIntoView = () => {
    let lanes = window.document.getElementsByClassName(`${prefixCls}-lane`);
    let lastLane = lanes[lanes.length - 1];
    if (lastLane && lastLane.scrollIntoViewIfNeeded) {
      lastLane.scrollIntoViewIfNeeded();
    }
  };

  dispatchOperate = (operate, org) => {
    switch (operate) {
      case 'createSib':
        this.setState({
          addEditModalMode: 'add',
          addEditModalVisible: true,
          currentOrg: {
            // eslint-disable-next-line
            parent_oid: _.get(org, 'parent_oid'),
            level: _.get(org, 'level', 1),
            paths: _.get(org, 'paths', [])
          }
        });
        break;
      case 'createChild':
        this.setState({
          addEditModalMode: 'add',
          addEditModalVisible: true,
          currentOrg: {
            // eslint-disable-next-line
            parent_oid: _.get(org, '_id'),
            level: _.get(org, 'level', 1) + 1,
            paths: [..._.get(org, 'paths', []), _.get(org, '_id')]
          }
        });
        break;
      case 'manageSites':
        this.jumpToPortSites(org);
        break;
      case 'edit':
        this.setState({
          addEditModalMode: 'edit',
          addEditModalVisible: true,
          currentOrg: org
        });
        break;
      case 'delete':
        this.deleteOrganization(org);
        break;
      case 'addStaff':
        this.setState({
          addStaffModalVisible: true,
          currentOrg: {
            // eslint-disable-next-line
            parent_oid: _.get(org, '_id'),
            level: _.get(org, 'level', 1) + 1,
            paths: [..._.get(org, 'paths', []), _.get(org, '_id')]
          }
        });
        break;
      default:
        return;
    }
  };

  jumpToPortSites = org => {
    const name = _.get(org, 'name');
    this.props.assetManageActions.resetQuery({ search: `exact:organization="${name}"` });
    this.props.history.push('/asset-manage');
  };

  deleteOrganization = org => {
    let id = _.get(org, '_id'),
      siteCount = _.get(org, 'site_count', 0),
      hasChildren = _.get(org, 'has_children', false),
      hasIpSegment = _.get(org, 'hasIpSegment', false);
    if (siteCount || hasChildren || hasIpSegment) {
      message.info('无法删除！请确认该部门是否有所属资产或所属IP段或存在下属部门');
      return;
    }
    deleteOrganization(id)
      .then(res => {
        if (_.get(res, 'data.result')) {
          message.success('删除该部门成功');
          let { expaneds = [] } = this.state;
          let deletedIndex = expaneds.indexOf(id);
          this.setState({ expaneds: expaneds.slice(0, deletedIndex + 1) });
          this.loadOrganizationTree('all');
          this.loadOrganizationCascaderTree();
        } else {
          message.error('删除该部门失败');
        }
      })
      .catch(e => {
        message.error(`删除该部门失败: ${e.message}`);
      });
  };

  afterAddEdit = () => {
    this.setState({ addEditModalVisible: false }, async () => {
      await this.loadOrganizationTree('all');
      setTimeout(() => {
        this.loadOrganizationCascaderTree();
      }, 1000);
    });
  };
  onSearch = () => {
    const { staffFilter } = this.state;
    this.setState(
      {
        staffFilter: {
          pageSize: 10,
          page: 1,
          search: staffFilter.search,
          orgs: []
        },
        selectTreeNode: ''
      },
      () => this.loadStaffList()
    );
  };

  renderTreeNode = data =>
    data.map(element => {
      if (_.get(element, 'children', []).length > 0) {
        return (
          <TreeNode
            icon={<Icon type="folder" />}
            title={
              <TreeNodeTitle
                nodeData={element}
                dispatchOperate={this.dispatchOperate}
                user={this.props.user}
              />
            }
            key={element._id}
          >
            {this.renderTreeNode(element.children)}
          </TreeNode>
        );
      } else {
        return (
          <TreeNode
            icon={<Icon type="folder" />}
            title={
              <TreeNodeTitle
                nodeData={element}
                dispatchOperate={this.dispatchOperate}
                user={this.props.user}
              />
            }
            key={element._id}
          />
        );
      }
    });

  addTopLevelOrg = () => {
    this.dispatchOperate('createSib', {
      // eslint-disable-next-line
      parent_oid: null,
      level: 1,
      paths: []
    });
  };

  handleOrgSelect = orgId => {
    this.setState(
      {
        staffFilter: {
          pageSize: 10,
          page: 1,
          search: '',
          orgs: [orgId]
        },
        selectTreeNode: orgId
      },
      () => this.loadStaffList()
    );
  };

  onTableChange = ({ current }, filters) => {
    const curFilter = { ...this.state.staffFilter };
    curFilter.page = current;
    if (filters) {
      curFilter.role = filters.roleInfo;
    }

    this.setState({ staffFilter: curFilter }, () => this.loadStaffList());
  };

  onEditRowChange = editRow => {
    this.setState({ editRow });
  };

  onBatchEditStaffIdsChange = batchEditStaffIds => {
    this.setState({ batchEditStaffIds });
  };

  batchAddOrg = () => {
    this.setState({
      batchOrgVisible: true
    });
  };

  closeBatchAddOrgModal = () => {
    this.setState({
      batchOrgVisible: false
    });
  };

  render() {
    let {
      addEditModalMode,
      addEditModalVisible,
      addStaffModalVisible,
      organizationTree,
      currentOrg,
      expaneds,
      organizationCascaderTree,
      autoSyncLdapVisible,
      staffList,
      staffLoading,
      staffCount,
      AllStaffCount,
      staffFilter,
      editRow,
      selectTreeNode,
      batchEditStaffIds,
      LdapConfig,
      batchOrgVisible
    } = this.state;
    let organizations = [];
    if (organizationTree.length) {
      organizations = [organizationTree];
      let currentLevel = 1;
      for (let expaned of expaneds) {
        let next = organizations[currentLevel - 1].find(item => item._id === expaned);
        let children = _.get(next, 'children', []);
        organizations.push(children);
        if (!children.length) {
          break;
        }
        currentLevel++;
      }
    }

    return (
      <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
        <div className={`${prefixCls}-gap-line`} />
        <div className={`${prefixCls}-content-wrapper`}>
          <div className={'org-tree'}>
            <div className="button-box">
              <Dropdown
                overlay={() => (
                  <Menu>
                    <Menu.Item onClick={() => this.addTopLevelOrg()}>人工添加部门</Menu.Item>
                    <Menu.Item onClick={() => this.batchAddOrg()}>批量添加部门</Menu.Item>
                  </Menu>
                )}
              >
                <Button icon="plus" type="primary" style={{ marginRight: 10 }}>
                  添加部门
                </Button>
              </Dropdown>
              <Button icon="diff" onClick={() => this.setState({ autoSyncLdapVisible: true })}>
                自动同步配置
              </Button>
            </div>
            <div className={`${prefixCls}-gap-line`} />
            <div className="button-box">
              全部共计&ldquo;<span style={{ color: '#0c64d0' }}>{AllStaffCount}</span>&ldquo;个人员
            </div>
            <div className={`${prefixCls}-gap-line`} />
            <div className={`${prefixCls}-tree-wrapper`}>
              <Tree
                showIcon
                blockNode
                defaultExpandAll
                switcherIcon={<Icon type="caret-down" />}
                onSelect={([id]) => this.handleOrgSelect(id)}
                selectedKeys={[selectTreeNode]}
              >
                {this.renderTreeNode(organizationCascaderTree || [])}
              </Tree>
            </div>
          </div>
          <div className={'staff-list'}>
            <Spin spinning={staffLoading}>
              <StaffList
                staffList={staffList}
                staffFilter={staffFilter}
                total={staffCount}
                history={this.props.history}
                onTableChange={this.onTableChange}
                loadStaffList={this.loadStaffList}
                showAddStaffModal={() => this.setState({ addStaffModalVisible: true })}
                onEditRowChange={this.onEditRowChange}
                onBatchEditStaffIdsChange={this.onBatchEditStaffIdsChange}
                loadOrganizationCascaderTree={this.loadOrganizationCascaderTree}
                onSearch={this.onSearch}
                SearchOnChange={e => {
                  this.setState({ staffFilter: { ...staffFilter, search: e } });
                }}
              />
            </Spin>
          </div>
          <AddEditModal
            mode={addEditModalMode}
            visible={addEditModalVisible}
            levelCN={nzhcn.encodeS(_.get(currentOrg, 'level', 1))}
            level={_.get(currentOrg, 'level')}
            currentOrg={currentOrg}
            onCancel={() => this.setState({ addEditModalVisible: false })}
            onOk={this.afterAddEdit}
            cascaderTree={organizationCascaderTree}
          />
          <AddStaffModal
            visible={addStaffModalVisible}
            currentOrg={currentOrg}
            editRow={editRow}
            batchEditStaffIds={batchEditStaffIds}
            onCancel={() =>
              this.setState({ addStaffModalVisible: false, editRow: null, batchEditStaffIds: [] })
            }
            levelCN={nzhcn.encodeS(_.get(currentOrg, 'level', 1))}
            level={_.get(currentOrg, 'level')}
            cascaderTree={organizationCascaderTree}
            loadStaffList={this.loadStaffList}
            loadOrganizationCascaderTree={this.loadOrganizationCascaderTree}
          />
          {autoSyncLdapVisible && (
            <AutoSyncLdapModal
              visible={autoSyncLdapVisible}
              onCancel={() => this.setState({ autoSyncLdapVisible: false })}
              LdapConfig={LdapConfig}
              currentOrg={currentOrg}
              cascaderTree={organizationCascaderTree}
              onCallback={param => this.setState(param)}
            />
          )}
          <BatchUploadOrgModal
            visible={batchOrgVisible}
            onClose={this.closeBatchAddOrgModal}
            loadOrganizationCascaderTree={this.loadOrganizationCascaderTree}
          />
        </div>
      </div>
    );
  }
}

Organization.propTypes = {
  history: PropTypes.object,
  assetManageActions: PropTypes.object,
  user: PropTypes.object
};
const mapStateToProps = state => {
  return {
    user: _.get(state, 'auth.user', {})
  };
};
const mapDispatchToProps = dispatch => {
  return {
    assetManageActions: bindActionCreators(assetManageActions, dispatch)
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Organization);
